package com.knife.lov.domain.service.impl;

import com.knife.lov.domain.service.KnifeAbstractLovCacheAble;
import com.knife.lov.infra.constants.CodeValueSupportType;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

/**
 * 注意本类有一个bug是，当同时对一个值集进行获取不同的属性时，由于本地缓存的原因会获取到不正确的数据；建议对不同属性进行翻译时，清除一次缓存
 * @author tianhao.luo@hand-china.com
 * @date 2021年11月15日 10:54 上午
 */
@Component
public class KnifeLovCacheAble extends KnifeAbstractLovCacheAble {

    /**
     * 本地缓存
     * @author tianhao.luo@hand-china.com
     * @date 2021/11/16 2:57 下午
     */
    public static ThreadLocal<Map<String, Map<CodeValueSupportType, Map<String,String>>>> lovCache = ThreadLocal.withInitial(() -> new HashMap<>(512));

    @Resource
    private KnifeRedisCacheAble redisCacheAble;

    @Override
    protected String selectMeaning(String lovCode, String source, CodeValueSupportType codeValueSupportType) {
        // 1 如果当前线程缓存中没有就去走redis，redis没有就走数据库
        Map<String, Map<CodeValueSupportType, Map<String, String>>> lovCodeMap = lovCache.get();
        Map<CodeValueSupportType, Map<String, String>> codeValueSupportTypeMap = lovCodeMap.getOrDefault(lovCode,new HashMap<>(10));
        lovCodeMap.putIfAbsent(lovCode,codeValueSupportTypeMap);
        Map<String, String> lovValueMap = codeValueSupportTypeMap.get(codeValueSupportType);
        String meaning;
        if (Objects.nonNull(lovValueMap)) {
            meaning = lovValueMap.get(source);
            // 本地线程有，就从缓存中获取
            if (!StringUtils.hasLength(meaning)) {
                // 走redis
                meaning = redisCacheAble.selectMeaning(lovCode, source, codeValueSupportType);
                lovValueMap.put(source, meaning);
            }
        } else {
            // 本地没有缓存，需要通过redis进行初始化
            meaning = redisCacheAble.selectMeaning(lovCode, source,codeValueSupportType);
            lovValueMap = new HashMap<>(10);
            lovValueMap.put(source, meaning);
            codeValueSupportTypeMap.put(codeValueSupportType,lovValueMap);
        }
        return meaning;
    }

    /**
     * 移除当前线程缓存
     * @author tianhao.luo@hand-china.com
     * @date 2021/11/16 3:00 下午
     */
    @Override
    protected void clear(){
        redisCacheAble.clear();
        lovCache.remove();
    }
}
